#include "vl_message_queue.h"

using namespace VL;

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:48:01
 * 
 * 构造函数
 */
VLMessageQueueThread::VLMessageQueueThread(): status(VLMessageQueueThreadStatus::MQTS_Init), looper(nullptr), threadPtr(nullptr), typeCallback(nullptr) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:48:01
 * 
 * 构造函数
 * 
 * @param looper 消息队列消费回调
 */
VLMessageQueueThread::VLMessageQueueThread(VLMessageQueueLooper looper): status(VLMessageQueueThreadStatus::MQTS_Init), looper(looper), threadPtr(nullptr), typeCallback(nullptr) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:57:22
 * 
 * 析构函数
 */
VLMessageQueueThread::~VLMessageQueueThread() {
	this->destroy();
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:49:01
 * 
 * 开始消息队列循环
 */
void VLMessageQueueThread::loop() {
	this->mutex.lock();
	if(this->status != MQTS_Init) {
		this->mutex.unlock();
		return;
	}
	this->status = MQTS_Looping;
	this->mutex.unlock();
	this->onLoopBegin();
	this->threadPtr.reset(new std::thread([&](){
		while(this->status == MQTS_Looping || this->status == MQTS_WaitDestroy) {
			std::shared_ptr<VLMessageQueueData> dataPtr;
			
			if(this->status == MQTS_WaitDestroy) {
				dataPtr = this->messageQueue.dequeue();
				if(dataPtr.get() == nullptr) {
					return;
				}
			} else {
				dataPtr = this->messageQueue.dequeueBlock();
			}
			this->onLoop(dataPtr);
		}
	}));
}
/**
 * @Author: CimZzz
 * @Date: 2022-08-27 14:14:37
 * 
 * 等待消息队列线程销毁
 */
void VLMessageQueueThread::waitDestroy() {
	std::unique_lock<std::mutex> locker(this->mutex);
	if(this->status == MQTS_Destroy) {
		return;
	}
	this->cond.wait(locker);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:49:17
 * 
 * 销毁消息队列线程
 */
void VLMessageQueueThread::destroy() {
	this->mutex.lock();
	if(this->status == MQTS_Destroy) {
		this->mutex.unlock();
		return;
	}
	this->status = MQTS_Destroy;
	this->mutex.unlock();
	this->messageQueue.destroy();
	this->onLoopEnd();
	// 等待线程结束
	if(this->threadPtr.get() != nullptr && this->threadPtr->joinable()) {
		this->threadPtr->join();
	}
	this->cond.notify_all();
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-26 12:40:48
 * 
 * 直到消费完全部消息后, 销毁消息队列线程
 */
void VLMessageQueueThread::destroyUntil() {
	this->mutex.lock();
	if(this->status == MQTS_Destroy || this->status == MQTS_WaitDestroy) {
		this->mutex.unlock();
		return;
	}
	this->status = MQTS_WaitDestroy;
	this->messageQueue.setEnqueueable(false);
	this->onLooperWannaEnd();
	this->mutex.unlock();
	this->messageQueue.notifyAll();
	// 等待线程结束
	if(this->threadPtr.get() != nullptr && this->threadPtr->joinable()) {
		this->threadPtr->join();
	}
	this->destroy();
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 20:13:53
 * 
 * 清空消息队列中全部消息
 */
void VLMessageQueueThread::clear() {
	this->messageQueue.clear();
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-13 11:09:01
 * 
 * 注册对应消息类型回调
 * 
 * @param typeCode 类型码
 * @param looper 处理消息回调
 * 
 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
 */
void VLMessageQueueThread::registerTypeCallback(unsigned int typeCode, VLMessageQueueLooper looper) {
	std::lock_guard<std::mutex> locker(this->mutex);
	if(this->status == MQTS_Destroy || this->status == MQTS_WaitDestroy || this->status == MQTS_Looping) {
		return;
	}
	if(this->typeCallback.get() == nullptr) {
		this->typeCallback.reset(new std::unordered_map<unsigned int, VLMessageQueueLooper>());
	}
	this->typeCallback->emplace(typeCode, looper);
}


/**
 * @Author: CimZzz
 * @Date: 2022-09-13 14:56:12
 * 
 * 注册对应消息类型回调, 不处理消息内容
 * 
 * @param typeCode 类型码
 * @param callback 处理消息回调
 * 
 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
 */
void VLMessageQueueThread::registerTypeCallback(unsigned int typeCode, std::function<void()> callback) {
	this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
		callback();
	});
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-15 17:04:15
 * 
 * 注册对应消息类型同步回调
 * 
 * @param typeCode 类型码
 * @param callback 处理消息回调
 * 
 *  @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
 */
void VLMessageQueueThread::registerTypeSyncCallback(unsigned int typeCode, std::function<void(const std::shared_ptr<VLMessageQueueData>&, unsigned int syncCode)> callback) {
	this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
		callback(dataPtr, dataPtr->getSyncCode());
	});
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-15 17:04:15
 * 
 * 注册对应消息类型同步回调, 不处理消息内容
 * 
 * @param typeCode 类型码
 * @param callback 处理消息回调
 * 
 *  @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
 */
void VLMessageQueueThread::registerTypeSyncCallback(unsigned int typeCode, std::function<void(unsigned int syncCode)> callback) {
	this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
		callback(dataPtr->getSyncCode());
	});
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-27 19:13:08
 * 
 * 入队数据
 * @param dataPtr 消息队列数据指针
 */
void VLMessageQueueThread::enqueue(VLMessageQueueData* dataPtr) {
	this->messageQueue.enqueue(dataPtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 19:13:08
 * 
 * 入队数据
 * @param dataPtr 消息队列数据指针
 */
void VLMessageQueueThread::enqueue(std::shared_ptr<VLMessageQueueData> dataPtr) {
	this->messageQueue.enqueue(dataPtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 19:13:08
 * 
 * 入队数据, 插入到队首
 * @param dataPtr 消息队列数据指针
 */
void VLMessageQueueThread::enqueueFirst(VLMessageQueueData* dataPtr) {
	this->messageQueue.enqueueFirst(dataPtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 19:13:08
 * 
 * 入队数据, 插入到队首
 * @param dataPtr 消息队列数据指针
 */
void VLMessageQueueThread::enqueueFirst(std::shared_ptr<VLMessageQueueData> dataPtr) {
	this->messageQueue.enqueueFirst(dataPtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 01:05:36
 * 
 * 判断当前是否正在执行循环
 */
bool VLMessageQueueThread::isLooping() const {
	return this->status == VLMessageQueueThreadStatus::MQTS_Looping;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 19:26:51
 * 
 * 获取当前消息队列线程状态
 */
VLMessageQueueThreadStatus VLMessageQueueThread::getMessageQueueThreadStatus() const {
	return this->status;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:56:23
 * 
 * 消息队列启动回调
 */
void VLMessageQueueThread::onLoopBegin() {
	// nothing
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 01:07:06
 * 
 * 消息队列线程启动回调
 */
void VLMessageQueueThread::onLoopThreadBegin() {
	// nothing
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:55:08
 * 
 * 执行消息队列消费回调
 * 
 * @param dataPtr 消息数据指针
 */
void VLMessageQueueThread::onLoop(const std::shared_ptr<VLMessageQueueData>& dataPtr) {
	if(dataPtr.get() != nullptr) {
		this->callLooper(dataPtr);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 20:22:45
 * 
 * 消息队列线程期望终止
 * 由 [destroyUntil 触发]
 */
void VLMessageQueueThread::onLooperWannaEnd() {
	// nothing
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 01:07:06
 * 
 * 消息队列线程终止回调
 */
void VLMessageQueueThread::onLoopThreadEnd() {
	// nothing
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:56:41
 * 
 * 消息队列终止回调
 */
void VLMessageQueueThread::onLoopEnd() {
	// nothing
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 08:17:37
 * 
 * 调用回调
 * 
 * @param dataPtr 数据指针
 */
void VLMessageQueueThread::callLooper(const std::shared_ptr<VLMessageQueueData>& dataPtr) {
	VLMessageQueueLooper looper = this->looper;
	if(this->typeCallback.get() != nullptr && !this->typeCallback->empty()) {
		auto looperIter = this->typeCallback->find(dataPtr->getTypeCode());
		if(looperIter != this->typeCallback->end()) {
			looper = looperIter->second;
		}
	}
	if(looper) {
		looper(dataPtr);
	}
}